//
//  NetworkTools.swift
//  微博09项目
//
//  Created by mac on 15/9/3.
//  Copyright © 2015年 itcast. All rights reserved.
//

import UIKit
import AFNetworking
import ReactiveCocoa

enum RequestMethod:String{
    case GET = "GET"
    case POST = "POST"
}
class NetworkTools: AFHTTPSessionManager {

 // MARK : 网络信息
    private let clientId = "1547692931"
    private let appSecret = "4d29483cd073959d1b5f7adef8299191"
    
    let redirectUri = "http://www.baidu.com"
    
    //获取一个单例,并且设置baseURL
    static let shareTools: NetworkTools = {
        var instance = NetworkTools(baseURL: nil)
        //设置反序列化的支持格式
        instance.responseSerializer.acceptableContentTypes?.insert("text/plain")
        
        return instance
    }()
    //MARK: - OAuth 
    /// OAuth 授权URL
    var oauthUrl: NSURL {
       let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(clientId)&redirect_uri=\(redirectUri)"
        
        return NSURL(string: urlString)!
    }
    // MARK: - 发布微博 https://api.weibo.com/2/statuses/update.json
    func sendStatus(status:String,image:UIImage?) -> RACSignal{
        let params = ["status": status]
        
        if image == nil{
         return request(.POST, URLString: "https://api.weibo.com/2/statuses/update.json", parameters: params)
        }else{
            return upload("https://upload.api.weibo.com/2/statuses/upload.json", parameters: params,image:image!)
        }
       
    }
    /// 加载用户账户，如果用户还没有登录返回nil
    //获取accessToken
    func loadAccessToken(code:String) ->RACSignal{
        
        let urlString = "https://api.weibo.com/oauth2/access_token"
        let params = ["client_id": clientId,
            "client_secret": appSecret,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redirectUri]
   
        return request(.POST, URLString: urlString, parameters: params,withToken:false)
    }
    
    //加载“微博“数据
//     func loadStatus() -> RACSignal{
//        
//        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
//        return request(.GET, URLString: urlString, parameters: nil)
//        
//    }
    //MARK: - 微博数据
    
    //    since_id	若指定此参数，则返回ID比since_id大的微博（即比since_id时间晚的微博），默认为0。
    //    max_id	若指定此参数，则返回ID小于或等于max_id的微博，默认为0。
    //    count	false	int	单页返回的记录条数，最大不超过200，默认为20。
    func loadStatus(since_id since_id:Int ,max_id:Int) -> RACSignal{
        let urlString = "https://api.weibo.com/2/statuses/home_timeline.json"
        var params = [String:AnyObject]()
        if since_id > 0{
            params["since_id"] = since_id
        }else if max_id > 0{
            params["max_id"] = max_id - 1
        }
        return request(.GET, URLString: urlString, parameters: params)
    }
    
  
    
    //MARK: - 加载用户信息
    func loadUserInfo(uid:String) -> RACSignal{
        let urlString = "https://api.weibo.com/2/users/show.json"
        let params = ["uid":uid]
        
        return request(.GET, URLString: urlString, parameters: params)
    }
    //MARK: - 私有方法，封装AFN的网络请求的方法
   
    private func appendToken(inout parameters:[String: AnyObject]?) -> Bool{
        //增加token参数字典中的参数
        //判断token是否存在，guard 刚好和if let相反
        guard let token = UserAccountViewModel.shareUserAccount.accessToken else{
          
            return false
        }
        if parameters == nil{
            parameters = [String : AnyObject]()
        }
        //后续的参数字典是有值的
        parameters!["access_token"] = token
        
        return true
    }
    
   private func request(method:RequestMethod,URLString:String,var parameters:[String:AnyObject]?,withToken:Bool = true) -> RACSignal{
        ///subscriber 这个值是自己随便写的含有特殊意义的变量
        return RACSignal.createSignal({ (subscriber) -> RACDisposable! in
    
            //判断是否需要token，
            if withToken && !self.appendToken(&parameters){
                subscriber.sendError(NSError(domain: "com.itheima.error", code: -1001, userInfo: ["errorMessage": "Token 为空"]))
                return nil
            }
            
            //1.成功的回调闭包
            let successCallBack = {(task:NSURLSessionDataTask,result:AnyObject) ->Void in
                subscriber.sendNext(result)
                // 完成
                subscriber.sendCompleted()
            }
            let failureCallBack = {(task:NSURLSessionDataTask,error: NSError) -> Void in
                ///subscriber 订阅者
                print(error)
                subscriber.sendError(error)
            }
            //根据不同的方法选择调用不同的网络方法
            if method == RequestMethod.GET {
                self.GET(URLString, parameters: parameters, success: successCallBack, failure: failureCallBack)
            }else
            {
                self.POST(URLString, parameters: parameters, success: successCallBack, failure: failureCallBack)
            }
            return nil
        
        })
    }
    //上传文件
    private func upload(URLString: String, var parameters: [String: AnyObject]?, image: UIImage) ->RACSignal {
        return RACSignal.createSignal() { (subscriber) -> RACDisposable! in
           //0.判断是否需要token - 将代码放在最合适的地方
            if !self.appendToken(&parameters){
                subscriber.sendError(NSError(domain: "com.itheima.error", code: -1001, userInfo: ["errorMessage": "Token 为空"]))
                return nil
            }
            
            //调用AFN 的文件上传的方法
            self.POST(URLString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
                //将图像转换成二进制数据
                let data = UIImagePNGRepresentation(image)!
                
                // formData 是遵守协议的对象，AFN内部提供的，使用的时候，只需要按照协议方法传递参数即可！
                /**
                1. 要上传图片的二进制数据
                2. 服务器的字段名，开发的时候，咨询后台
                3. 保存在服务器的文件名，很多后台允许随便写
                4. mimeType -> 客户端告诉服务器上传文件的类型，格式
                大类/小类
                image/jpg
                image/gif
                image/png
                如果，不想告诉服务器具体的类型，可以使用 application/octet-stream
                */
                formData.appendPartWithFileData(data, name: "pic", fileName: "ohoh", mimeType: "application/octet-stream")

                }, success: { (_, result) -> Void in
                    subscriber.sendNext(result)
                    subscriber.sendCompleted()
                }, failure: { (_, error) -> Void in
                    printLog(error, logError: true)
                    
                    subscriber.sendError(error)
            })
            return nil
            
        }
    }


}
